///终端业务机会 阶段变更
public without sharing class OppTerminalController {
    
     public String msg  {get ; private set;}

    public Boolean isErr {get; private set;}

    public Boolean isSuccess {get; private set;}

    public String backId {get; private set;}

    public String dataJson {get; private set;}
    public String saveJson {get;  set;}
    private Map<String,DataUtil.SObjectBean> stageObjectMap ; 
    public String  contactdeptcombox {private set; get;}

    public class ControllerException extends Exception {}
    public Boolean isNew {private set; get;}

    public Opportunity opp {get ;set ;}
    public Boolean isDrop {private set; get; }
    public String currentStage ;
    public String newContractURL {private set;get;}

    public OppTerminalController() {
           opp = new Opportunity();
        backId = System.currentPageReference().getParameters().get('id');
        stageObjectMap = new Map<String,DataUtil.SObjectBean>();
        isNew = false;
        currentStage = '';
        isDrop = System.currentPageReference().getParameters().get('drop') != null ;
    }
  
    public void init(){
        try {
            Map<String,Object> dataMap  = new Map<String ,Object>();
            if(backId == null){
                setError('页面打开错误!');
            }else if(Id.valueOf(backId).getSObjectType() == Account.SObjectType ){


            
                Account acc = [select Id ,MKCooperationType__c from Account where Id =:backId];

                String current = acc.MKCooperationType__c == null ? '3':acc.MKCooperationType__c ;
                opp.CurrentProject__c = current;
                opp.AccountId = backId;
                isNew = true ;
                dataMap.put('base',getOpp(backId));

            }else if(Id.valueOf(backId).getSObjectType() == Opportunity.SObjectType ){
                 dataMap.put('base',getOpp(backId));
                if(opp.StageName == '意向'){
                    dataMap.put('dept',getDeptInfo());
                    dataMap.put('contact',getContactInfo());
                }
                currentStage = opp.StageName ;
            }
            if(!isNew){
               Opportunity opp1 = [select Id ,AccountId ,StageName,RecordType.Name from Opportunity where Id=:backId];
                newContractURL = '/flow/NewContract?OppID='+opp1.Id+'&AccountID='+opp1.AccountId+'&Stage='+opp1.StageName+'&RecordType='+opp1.RecordType.Name;
            }



            if(!isNew && (isDrop && (opp.StageName == '合同签订' || opp.StageName == '失败' ))) setError('业务机会'+opp.StageName +'阶段不能操作!');
            if(!isNew && !isDrop){

                if(opp.StageName == '意向'){

                    if(!([select count() from IntentProduct__c where Opportunity__c =:opp.Id  ] > 0)  && opp.IntentionalProductRange__c != '试剂'){
                        setError( '请选择意向产品!');
                    }
                }else if(opp.StageName == '立项'){
                    
                    if(!( [select count() from InstrumentPolicy__c where Opportunity__c =: opp.Id and Status__c in ('审批中','审批中(销售主管已批准)','已批准','已拒绝') ] > 0 || [select count() from Quote where OpportunityId =:opp.Id and Status in ('申请中','已批准','已拒绝')] > 0 || 
                       [select count() from Measure_Calculate__c where Opportunity__c =:opp.Id and Status__c in ('已提交','审批拒绝','审批成功') ] > 0 || [select count() from BloodSugarOrder__c where Opportunities__c =:opp.Id and Status__c in ('审批中','审批拒绝','审批成功')] > 0 )  ){

                        setError('没有提交中/审批成功/审批拒绝的报价或测算,政策,血糖仪配送申请!请先操作报价或者测算,政策!');
                    }
                }else if(opp.StageName == '方案谈判'){


                    if(!( [select count() from InstrumentPolicy__c where Opportunity__c =: opp.Id and Status__c ='已批准' ] > 0 || [select count() from Quote where OpportunityId =:opp.Id and Status = '已批准' ] > 0 || 
                       [select count() from Measure_Calculate__c where Opportunity__c =:opp.Id and Status__c ='审批成功' ] > 0 || [select count() from BloodSugarOrder__c where Opportunities__c =:opp.Id and Status__c = '审批成功' ] > 0) ){

                        setError('没有已批准的报价或测算,政策,血糖仪配送申请!请先操作报价或者测算,政策!');
                        
                    }
                }else if(opp.StageName == '招标'){
                    
                    if([select count() from ContractProduct__c where Opportunity__c =:opp.Id ] == 0 &&  [select count() from ContractReagentInformation__c where Opportunity__c =:opp.Id ] == 0 ){
                        setError( '请添加合作明细!');
                    }else{
                        setError('满足以下条件之一，终端客户业务机会自动升迁合同签订阶段:1、全部的合作仪器明细中主分类为仪器的产品均已安装；2、全部的合作仪器明细关联的合同均已生效（即OA合同流程归档）。');
                    }
                
                    
                }

            }

           
                //dataMap.put('winRito',getWinRtio(opp.Id ));
                dataMap.put('baseObject',DataUtil.getBaseObjectMap(stageObjectMap)); 
            
            dataJson = EncodingUtil.urlEncode(JSON.serialize(dataMap), 'UTF-8');
        }catch (Exception e) {
            
            ApexPages.addMessage( new ApexPages.Message(ApexPages.Severity.ERROR ,e.getMessage()));

        }   
        
    }

    public void upgradeToNext(){

        msg = '';
        
        
        

        Map<String,Object> saveMap = (Map<String,Object>) JSON.deserializeUntyped(EncodingUtil.urlDecode(saveJson,'UTF-8'));
           
           
        List<SObject> soList = new List<SObject>();

        //基础信息
        Map<String,Object> baseMap = (Map<String,Object>) saveMap.get('base');

        try{
          
            for(String objname : stageObjectMap.keySet()){

                Map<String,Object> dataMap = (Map<String,Object> ) baseMap.get(objname);
                DataUtil.SObjectBean sb  = stageObjectMap.get(objname);

                SObject so = sb.stype.newSObject();
                if(isNew && objname =='Opportunity'){
                    so.put('StageName', '意向');
                    so.put('Name', '系统设置');
                    so.put('AccountId', opp.AccountId);
                    so.put('RecordTypeId',Utils.getRecordTypeIdByDevNameAndObjName('CustomerOpportunity', 'Opportunity'));
                }
                Map<String,Set<String>> fieldsMap = getFields(opp.StageName);
          
                Map<String,DataUtil.FieldBean> fbeanMap = DataUtil.getFieldsInfo(sb.stype,fieldsMap.get(objname));
                for(String field : fieldsMap.get(objname)){
                    System.debug(field);
                    if(dataMap.containsKey(field))so.put(field, DataUtil.dataHandler(dataMap.get(field),fbeanMap.get(field).type.toUpperCase() ));
                }
                if(sb.idvalue != null ) so.put('Id', sb.idvalue);
                soList.add(so);
            }
        }catch(Exception e){
             opp.StageName = currentStage;
            msg = '操作失败:'+e.getCause()+e.getStackTraceString();
            System.debug('OppTerminalController==>'+ msg);
            return;
        }
        

        List<Department__c> deptList = new List<Department__c>();
        List<Contact> conctactList = new List<Contact>();
        System.debug('opp.StageName==>'+(opp.StageName == '意向'));
        if(opp.StageName == '意向'){
            //科室
            List<Object> depts  = (List<Object>) saveMap.get('dept');
            if(depts != null ){
                for(Object o : depts){
                    Map<String,Object> mo = (Map<String,Object>) o;
                    Department__c  d = new Department__c();
                    String deptId = DataUtil.getStringValue(mo.get('deptId'));
                    if(deptId != null && deptId != '') d.Id = deptId;
                    d.hospitalDepartments__c =  DataUtil.getStringValue(mo.get('name'));

                    if(d.Id == null )d.TerminalCustomer__c = DataUtil.getStringValue(mo.get('accId'));
                    d.LastYearRevenue__c = DataUtil.getDecimalValue(mo.get('lastProfit'));
                    d.PurchasingCost__c = DataUtil.getDecimalValue(mo.get('lastBuy'));
                    deptList.add(d);
                }

            }
            
            Id contactRT = Utils.getRecordTypeIdByDevNameAndObjName('TerminalCustomer', 'Contact');
            //联系人
            List<Object> contacts   = (List<Object>) saveMap.get('contact');
             System.debug('contacts==>'+contacts);
            if(contacts != null ){
                for(Object o : contacts){
                   
                    Map<String,Object> mo = (Map<String,Object>) o;
                    Contact  c = new Contact();

                    String contactId = DataUtil.getStringValue(mo.get('contactId'));
                    if(contactId != null && contactId != '') c.Id = contactId;
                    c.LastName   = DataUtil.getStringValue(mo.get('name'));
                    if(c.LastName == null || c.LastName == '') continue;
                    c.MobilePhone = DataUtil.getStringValue(mo.get('phone'));
                    c.Id = DataUtil.getStringValue(mo.get('contactId'));

                    if(c.Id == null )c.AccountId = DataUtil.getStringValue(mo.get('accId'));
                    c.RecordTypeId = contactRT;
                    c.Post__c =DataUtil.getStringValue(mo.get('post'));
                    c.Departments__c = DataUtil.getStringValue(mo.get('dept'));
                    conctactList.add(c);
                }

            }
            
        }
        
        if(!isNew){
                if(opp.StageName == '方案谈判') opp.StageName= '招标';
                if(opp.StageName == '立项') opp.StageName= '方案谈判';
                if(opp.StageName == '意向') opp.StageName= '立项';
                if(isDrop) opp.StageName = '失败';
                
        }
        //赢单率
        /*List<Object> winRitoList = (List<Object> )saveMap.get('winRito');

        List<StageWinRate__c> slist =isNew ? new List<StageWinRate__c>() : [select Id, Name from StageWinRate__c where Opportunity__c =: opp.Id  and Name=:opp.StageName order by CreatedDate desc limit 1];
        StageWinRate__c swr = slist.size() == 0 ? new StageWinRate__c(Name=opp.StageName) : slist[0] ;
        
        List<WinRatioTeam__c> nwList = new List<WinRatioTeam__c>();
        
        if(!isDrop){

            Decimal perc = 0; 
            for(Object o : winRitoList){
                Map<String,Object> mo = (Map<String,Object> )o;
                WinRatioTeam__c wrt = new WinRatioTeam__c();

                wrt.Weight__c = DataUtil.getDecimalValue(mo.get('rito'));
                if(wrt.Weight__c == null || wrt.Weight__c == 0 ){
                    msg = '权重不能为空';
                    return ;
                }
                wrt.SupportRatio__c = DataUtil.getDecimalValue(mo.get('support'));
                if(wrt.SupportRatio__c == null || wrt.SupportRatio__c == 0 ){
                    msg = '支持率不能为空';
                    return ;
                }
                perc += wrt.SupportRatio__c * wrt.Weight__c / 100 ;
                wrt.Opportunity__c = opp.Id;
                wrt.Name = DataUtil.getStringValue(mo.get('name'));
                wrt.contact__c = DataUtil.getStringValue(mo.get('contactId'));
                //wrt.StageWinRate__c =slist[0].Id;
                nwList.add(wrt);
            }

            if(perc > 100){
                
                msg = Label.Err_WeightRule;
                return ;
            }
            
        }
        */
        

            System.debug('OppTerminalController ==>'+ opp);

        Savepoint sp = Database.setSavepoint();
        try {
            if(soList.size() > 0){
                for(SObject so : soList ){
                    if(so.get('Id') != null ){
                        update so ;
                    }else{
                        insert so ;
                        if(isNew) backId = String.valueOf(so.get('Id'));
                        if(Id.valueOf(backId).getSObjecttype() == Opportunity.SObjectType )opp.Id = backId;
                    }
                }
            }
            
            

            /*if(!isDrop){
                if(swr.Id != null )delete [select Id from WinRatioTeam__c where StageWinRate__c =:swr.Id ];
                if(swr.Id == null )swr.Opportunity__c = opp.Id ;
                upsert swr ; 
                for(WinRatioTeam__c wrt : nwList){
                    wrt.StageWinRate__c =swr.Id;
                    wrt.Opportunity__c = opp.Id ;
                }
                if(nwList.size() > 0 ) insert nwList;

            }*/
            
            if(deptList.size() > 0) upsert deptList;
            System.debug('OppTerminalController==>'+conctactList);
            if(conctactList.size() > 0) upsert conctactList;

            update opp ;
            isSuccess = true;
            msg = '操作成功!';
        }catch (Exception e) {
            if(isNew){
                opp.Id = null;
                
            } 
            opp.StageName = currentStage;
            Database.rollback(sp); 
            System.debug('OppTerminalController==>'+ e.getMessage() + e.getStackTraceString());
            isSuccess = false;
            msg = '操作失败:'+e.getMessage();

        }
        



    }

    ///获取科室
    private List<DeptBean> getDeptInfo(){
        List<DeptBean> tmp = new List<DeptBean>();
        List<String> depts =  opp.Department__c.split(';');
        Map<String ,Department__c> deptMap = new Map<String,Department__c>();
        for(Department__c d: [select Id ,TerminalCustomer__c,PurchasingCost__c ,HospitalDepartments__c,LastYearRevenue__c 
            from Department__c where TerminalCustomer__c =:opp.AccountId and  HospitalDepartments__c in: depts]){
            
            deptMap.put(d.hospitalDepartments__c, d);
        }
        for(String dept :depts){
            DeptBean db =  null;
            if(deptMap.containsKey(dept)){
                db = new DeptBean(deptMap.get(dept));
            }else{
                db = new DeptBean();
                db.name = dept;
                db.accId = Opp.AccountId;
            }
            tmp.add(db );
        }
        return tmp ;
    }
    ///获取联系人
    private List<ContactBean> getContactInfo(){
        List<ContactBean> tmp = new List<ContactBean>();
         Set<String> needPost = new Set<String>{'院长','分管院长(设备)','检验科','设备科/工程部/维修科','财务科/计财处'};

        for(Contact con : [select Id, Name ,MobilePhone ,Post__c,Departments__c ,AccountId  from Contact where AccountId =:opp.AccountId ]){

             if(null==con.Post__c || String.isBlank(con.Post__c) )continue;
            
            if(con.Post__c=='院长'){
                needPost.remove(con.Post__c);
                tmp.add( new ContactBean(con));
            }else if(con.Post__c=='分管院长(设备)'){
                needPost.remove('分管院长(设备)');
                tmp.add( new ContactBean(con));
            }else if(con.Post__c =='科长/主任'){
                if(null!=con.Departments__c){
                    if(con.Departments__c == '检验科'){
                        needPost.remove('检验科');
                        tmp.add( new ContactBean(con));
                    }else if(con.Departments__c == '设备科/工程部/维修科'){
                        needPost.remove('设备科/工程部/维修科');
                         tmp.add( new ContactBean(con));
                    }else if(con.Departments__c=='财务科/计财处'){
                        needPost.remove('财务科/计财处');
                        tmp.add( new ContactBean(con));
                    }
                }
            }
        }
        List<Map<String,String>> contactdept = new List<Map<String,String>> ();
        for(String post : needPost ){
            ContactBean cb = new ContactBean();
            if(post.contains('科')){
                cb.dept = post ;
                cb.post = '科长/主任';
            }else{
                cb.post = post ;
            }
            if(post.contains('院长'))cb.dept = '医院办公室';
            cb.accId = opp.AccountId;
            tmp.add(cb);

        }
        //contactdeptcombox =EncodingUtil.urlEncode(JSON.serialize(contactdept),  'UTF-8') ;

        return tmp ; 

    }


    ///获取前面阶段的赢单率
    /*
    private List<WinRitoBean> getWinRtio(String opp_id){
        
        Map<String,WinRatioTeam__c> wrtMap = new Map<String,WinRatioTeam__c>();
        //业务机会阶段信息
        if(!isNew){
             List<StageWinRate__c> slist =  [select Id, Name from StageWinRate__c where Opportunity__c =: opp_id  and Name=:opp.StageName  ]; 
                    
            //赢单率小组
            for(WinRatioTeam__c wo : [select Id,Weight__c,SupportRatio__c ,Contact__c from WinRatioTeam__c where StageWinRate__c =:slist[0].Id]){
                wrtMap.put(wo.Contact__c, wo);
            }
        }
        


        List<WinRitoBean> wbList = new List<WinRitoBean>();
        for(Contact c : [select Id, Name, Post__c, Departments__c from Contact where AccountId =: opp.AccountId ]){
             wbList.add(new WinRitoBean(c,opp.StageName,wrtMap.get(c.Id) ));
        }

        return wbList;

    }*/

   
    
    private Map<String,Set<String> >  getFields(String stage ){
        Map<String,Set<String>> fieldsMap  = new  Map<String,Set<String>>();

        if(isDrop ){

            DataUtil.SObjectBean sb = new DataUtil.SObjectBean();

            sb.title ='业务机会基本信息';
            sb.objname = 'Opportunity';
            sb.stype = DataUtil.getSObjectType('Opportunity');
            sb.idvalue = opp.Id ;
            sb.type = 'base';
            sb.condition = ' where Id =\''+opp.Id+'\'';
            stageObjectMap.put('Opportunity',sb );

             Set<String>  fields = new Set<String>{'LostReason__c','Successfulcompany__c','Winningcompanychannel__c','LostReasoneDesc__c','SuccessfulModel__c','WhetherParticipate__c','ContractTime__c','SuccessfulBrand__c'};
            fieldsMap.put('Opportunity', fields);
            return fieldsMap;

        }
        if(isNew){
            DataUtil.SObjectBean sb = new DataUtil.SObjectBean();

            sb.title ='业务机会基本信息';
            sb.objname = 'Opportunity';
            sb.stype = DataUtil.getSObjectType('Opportunity');
            //sb.idvalue = opp.Id ;
            sb.type = 'base';
            //sb.condition = ' where Id =\''+opp.Id+'\'';
            stageObjectMap.put('Opportunity',sb );

             Set<String>  fields = new Set<String>{'CurrentProject__c','ExpectedCooperation__c','IntentionalProductRange__c','SalesType__c','ProjStartDate__c','CloseDate','SalesType__c','NewName__c','Department__c','SalesPriceSumYear__c','CooperationMode__c','WinRatio__c','ExecuteCompany__c'};
            fieldsMap.put('Opportunity', fields);

            DataUtil.SObjectBean accsb = new DataUtil.SObjectBean();

            accsb.title ='客户基本信息';
            accsb.objname = 'Account';
            accsb.stype = DataUtil.getSObjectType('Account');
            accsb.idvalue = opp.AccountId;
            accsb.type = 'base';
            accsb.condition = ' where Id =\''+opp.AccountId+'\'';
            stageObjectMap.put('Account',accsb );
            Set<String>  accfields = new Set<String>{'Category__c','Level__c','CustomerAttribute__c','Province__c','Address__c','City__c','Phone','District__c','SpecialDepart__c','BedNumOpen__c','LastYearRevenue__c'};

            fieldsMap.put('Account', accfields);

        }else if(stage == '意向' && !isNew){
            DataUtil.SObjectBean oppsb = new DataUtil.SObjectBean();

            oppsb.title ='业务机会基本信息';
            oppsb.objname = 'Opportunity';
            oppsb.stype = DataUtil.getSObjectType('Opportunity');
            oppsb.idvalue = opp.Id  ;
            oppsb.type = 'base';
            oppsb.condition = ' where Id =\''+opp.Id+'\'';
            stageObjectMap.put('Opportunity',oppsb );

            Set<String>  oppfields = new Set<String>{'WinRatio__c','ExecuteCompany__c'};

            fieldsMap.put('Opportunity', oppfields);

            DataUtil.SObjectBean sb = new DataUtil.SObjectBean();

            sb.title ='客户基本信息';
            sb.objname = 'Account';
            sb.stype = DataUtil.getSObjectType('Account');
            sb.idvalue = opp.AccountId ;
            sb.type = 'base';
            sb.condition = ' where Id =\''+opp.AccountId+'\'';
            stageObjectMap.put('Account',sb );
            Set<String>  fields = new Set<String>{'Category__c','Level__c','CustomerAttribute__c','Province__c','Address__c','City__c','Phone','District__c','SpecialDepart__c','BedNumOpen__c','LastYearRevenue__c'};

            fieldsMap.put('Account', fields);

        }else if(stage == '方案谈判'){
            DataUtil.SObjectBean oppsb = new DataUtil.SObjectBean();

            oppsb.title ='业务机会基本信息';
            oppsb.objname = 'Opportunity';
            oppsb.stype = DataUtil.getSObjectType('Opportunity');
            oppsb.idvalue = opp.Id  ;
            oppsb.type = 'base';
            oppsb.condition = ' where Id =\''+opp.Id+'\'';
            stageObjectMap.put('Opportunity',oppsb );
        

            Set<String>  oppfields = new Set<String>{'WinRatio__c','PurchaseRoot__c'};

            fieldsMap.put('Opportunity', oppfields);

        }else{
            DataUtil.SObjectBean oppsb = new DataUtil.SObjectBean();

            oppsb.title ='业务机会基本信息';
            oppsb.objname = 'Opportunity';
            oppsb.stype = DataUtil.getSObjectType('Opportunity');
            oppsb.idvalue = opp.Id  ;
            oppsb.type = 'base';
            oppsb.condition = ' where Id =\''+opp.Id+'\'';
            stageObjectMap.put('Opportunity',oppsb );
        

            Set<String>  oppfields = new Set<String>{'WinRatio__c'};

            fieldsMap.put('Opportunity', oppfields);
        }
        

        return fieldsMap;
    }
    
    private Map<String,List<DataUtil.FieldBean>> getOpp(String opp_id){

        if( !isNew )opp  = [select Id,ProjStartDate__c,CloseDate,CooperationMode__c,NewName__c,Department__c,
        SalesPriceSumYear__c,StageName,AccountId ,SalesType__c ,IntentionalProductRange__c 
         from Opportunity where Id=:opp_id];
        
         //opp.StageName = '立项';
        // Map<String,SObject> soMap = new Map<String,SObject>();
         //soMap.put('Opportunity', opp);

         System.debug(opp.StageName);
         Map<String,Set<String>> fieldsmap = getFields(opp.StageName);
         System.debug('OppTerminalController==>'+fieldsmap);
         Map<String, List<DataUtil.FieldBean>> fbMap = DataUtil.getFieldsBean(fieldsmap,stageObjectMap);
         System.debug('OppTerminalController==>'+fbMap);
         Map<String,List<DataUtil.FieldBean>> fields = DataUtil.setFieldsValue(fbMap,DataUtil.getBaseInfo(fbMap,stageObjectMap) );
         System.debug('OppTerminalController==>'+fields);

         if(isNew){
            for(DataUtil.FieldBean fb : fields.get('Opportunity')){
                if(fb.name == 'CurrentProject__c'){
                    fb.value = opp.CurrentProject__c;
                    break;
                }
            }
         }
         return fields;
    }

     //设置错误
    private void setError(String message){
        isErr = true;
      throw new ControllerException(message);

    }

    public void setNil(){
        dataJson = '';
    }

    public class DeptBean{
        public String deptId ; 
        public String name ; 
        public Decimal lastBuy ; 
        public Decimal lastProfit;
        public String accId ; 
        public DeptBean(){}
        public DeptBean(Department__c d ){
            deptId = d.Id ; 
            name = d.hospitalDepartments__c;
            lastBuy = d.PurchasingCost__c;
            lastProfit = d.LastYearRevenue__c;
            accId = d.TerminalCustomer__c;
        }
    }
    public class ContactBean{
        public String name ; 
        public String post ; 
        public String phone ;
        public String contactId;
        public String accId ; 
        public String dept ; 
        public ContactBean(){}
        public ContactBean(Contact c ){
            contactId = c.Id ;
            post = c.Post__c;
            phone = c.MobilePhone;
            dept = c.Departments__c;
            name = c.Name;
            accId = c.AccountId;

        }


    }

/*
    public class WinRitoBean{
        public Boolean ck ; 
        public String contactId ;
        public String name ;
        public String post ;
        public String dept ; 
        public Decimal support ; 
        public Decimal rito ; 
        public String stage ;

        public WinRitoBean(Contact c ,String stg , WinRatioTeam__c wrt ){

            contactId = c.Id ; 
            name = c.Name;
            post = c.Post__c;
            dept = c.Departments__c;
            if(wrt != null )support = wrt.SupportRatio__c;
            if(wrt != null )rito = wrt.Weight__c;
            ck = wrt != null; 
            stage = stg; 
        }
    }
    */
   
}